<?php 
declare(strict_types=1);

use Hyperf\Utils\Context;
use App\Core\AppKey;
use Hyperf\Utils\ApplicationContext;
use Psr\EventDispatcher\EventDispatcherInterface;



/**
 * 返回数据格式化
 * @param string $message
 * @param string $data
 * @param number $status
 * @return string[]
 */
function getResponseData($message, $data = null, $status = 0)
{
    return [
        'data' => $data,
        'message' => $message,
        'error' => $status
    ];
}

/**
 * 返回错误消息
 * @param string $message
 * @param number $code
 * @return void
 */
function responseError($message, $code = 500)
{
    throw new \App\Exception\HttpResponseException($message, $code);
}

/**
 * 设置携程上下文数据
 * @param string $id
 * @param mixed $value
 * @return void
 */
function setContext(string $id, $value)
{
    Context::set($id, $value);
}

/**
 * 获取携程上下文数据
 * @param string $id
 * @return mixed
 */
function getContext(string $id)
{
    return Context::get($id);
}

/**
 * 获取请求对象
 * @return Hyperf\HttpServer\Contract\RequestInterface;
 */
function R()
{
    return getContext(AppKey::CONTEXT_HTTP_REQUEST);
}

/**
 * 获取返回对象
 * @return Hyperf\HttpServer\Contract\ResponseInterface;
 */
function RS()
{
    return getContext(AppKey::CONTEXT_HTTP_RESPONSE);
}

/**
 * 获取请求参数
 * @param string $key
 * @return mixed
 */
function I($key = null)
{
    $data = getContext(AppKey::CONTEXT_HTTP_REQUEST_DATA) ?? null;
    if ($key) {
        $data = ($data[$key] ?? null) ?? ($data[\Hyperf\Utils\Str::camel($key)] ?? null);
    }
    
    return $data;
}

/**
 * 获取请求的端口
 * @return string
 */
function getHttpPort()
{
    return getContext(AppKey::CONTEXT_HTTP_REQUEST_PORT);  
}

function event($event)
{
    return ApplicationContext::getContainer()->get(EventDispatcherInterface::class)
    ->dispatch($event);
}

/**
 * 存储地址
 * @param  string $path
 * @return string
 */
function storagePath($path)
{
    return BASE_PATH.'/storage/'.ltrim($path, '/');    
}

/**
 * 存放资源目录
 * @param   string $path
 * @return string
 */
function resourcePath($path)
{
    return BASE_PATH.'/resource/'.ltrim($path, '/');
}

/**
 * 验证请求字段
 * @param array $rules
 * @param array $data
 * @return void
 */
function validate($pRules, $data = [])
{
    $rules = [];
    $attributes = [];
    $messages = [];
    foreach ($pRules as $rule){
        $rules[$rule[1]] = $rule[2];
        $attributes[$rule[1]] = $rule[0];
        if( ! empty($rule[3])){
            foreach ($rule[3] as $key => $message){
                $messages[$rule[1].'.'.$key] = $message;
            }
        }
    }
    $validator = ApplicationContext::getContainer()
    ->get('Hyperf\Validation\Contract\ValidatorFactoryInterface');
    $validator = $validator->make(($data ? $data : I()), $rules, $messages, $attributes);
    $errors = $validator->fails();
    if ($errors) {
        responseError($validator->errors()->first());
    }
}

/**
 * 获取客户端ip地址
 * @return mixed
 */
function getClientIp()
{
    $res = R()->getServerParams();
    if(isset($res['http_client_ip'])){
        return $res['http_client_ip'];
    }elseif(isset($res['http_x_real_ip'])){
        return $res['http_x_real_ip'];
    }elseif(isset($res['http_x_forwarded_for'])){
        //部分CDN会获取多层代理IP，所以转成数组取第一个值
        $arr = explode(',',$res['http_x_forwarded_for']);
        return $arr[0];
    }
    
    return $res['remote_addr'];
}

/**
 * 判断当前登录的人是否有权限
 * @param null $permissions
 * @param bool $isLocal
 * @return bool
 */
function checkPower($permissions = null, $isLocal = true)
{
    if ($permissions === null) {
        $permissions = getContext(AppKey::CONTEXT_HTTP_REQUEST_CONTROLLER_METHOED_PERMISSION);
    }
    
    if ( ! $permissions) {
        return true;
    }

    //如果是本服务的权限，需要自动加上应用名称前缀，是其他服务的权限需要在permissions参数中自动带上权限的前缀
    if ($isLocal) {
        $appName = config('app_name');
        foreach ($permissions as $i => $permission) {
            $permissions[$i] = $appName.'-'.$permission;
        }
    }

    $authUser = authUser();
    $diff = array_intersect($permissions, $authUser->permissions);
    if ( ! $diff) {
        return false;
    }
    
    return true;
}

/**
 * 获取授权人信息
 * @param string $key
 * @return mixed|null
 */
function authUser($key = null)
{
    $data = getContext(AppKey::CONTEXT_USER);
    if ($key && $data) {
        return $data[$key] ?? null;
    }
    return $data;
}

/**
 * 获取当前请求所属功能板块
 * @return Object
 */
function requestModulKey()
{
    return getContext(AppKey::CONTEXT_REQUEST_MODULE_KEY);
}

/**
 * 当前请求是否需要记录操作日志
 * @return Object
 */
function requestHasOperationLog()
{
    return getContext(AppKey::CONTEXT_REQUEST_HAS_OPERATION_LOG);
}

/**
 * 浮点格式转换
 * @param mixed $number
 * @param int $count
 * @param boolean $returnString
 * @return number
 */
function floatFormat($number, $count = 2, $returnString = false)
{
    if  ($returnString) {
        return floatval(round($number, $count)) . '';
    }
    
    return floatval(round($number, $count));
}

/**
 * 横线线转为驼峰
 * @param $str
 * @param bool $ucfirst
 * @return mixed|string
 */
function convertHorizontalline($str , $ucfirst = false)
{
    while(($pos = strpos($str , '-'))!==false) {
        $str = substr($str , 0 , $pos).ucfirst(substr($str , $pos+1));
    }

    return $ucfirst ? ucfirst($str) : $str;
}

/**
 * 下划线转为驼峰
 * @param $str
 * @param bool $ucfirst
 * @return mixed|string
 */
function convertUnderline($str , $ucfirst = true)
{
    while(($pos = strpos($str , '_'))!==false) {
        $str = substr($str , 0 , $pos).ucfirst(substr($str , $pos+1));
    }

    return $ucfirst ? ucfirst($str) : $str;
}


